#![no_std]
#![no_main]

use core::{
    arch::asm,
    cell::{OnceCell, UnsafeCell},
    error::Error,
    f32::consts,
    future::Future,
    mem::transmute,
    ops::BitXor,
    panic::PanicInfo,
    pin::{pin, Pin},
    prelude::rust_2021,
    task::{self, Context, RawWakerVTable, Waker},
};

use ch32l1::ch32l103::{self, rcc::CFGR0, Peripherals, GPIOA, GPIOB, RCC, SPI1, SYSTICK};
use display_interface::{DataFormat, DisplayError};
use display_interface_spi::SPIInterface;
use drivers::gpio::{CNF, GPIO};
use embedded_graphics::{
    iterator::raw,
    mono_font::{
        ascii::FONT_6X13_ITALIC, iso_8859_13::FONT_7X14_BOLD, MonoFont, MonoTextStyle,
        MonoTextStyleBuilder,
    },
    pixelcolor::{BinaryColor, Rgb565},
    prelude::*,
    primitives::{Circle, PrimitiveStyleBuilder, Rectangle, Triangle},
    text::{renderer::CharacterStyle, Baseline, Text},
};
use embedded_hal::{
    delay::DelayNs,
    digital::OutputPin,
    spi::{self, ErrorType, Operation, SpiBus, SpiDevice},
};
use embedded_io::Write;
use heapless::{spsc::Queue, Vec};
use numtoa::NumToA;
use runtime::SimpleRuntime;
use ssd1306::{
    mode::{BasicMode, BufferedGraphicsMode},
    prelude::*,
    Ssd1306,
};

use riscv::{asm::delay, paste};
use usart::MyUsart;
mod drivers;
mod usart;

#[no_mangle]
#[allow(non_snake_case)]
unsafe fn SystemInit() {
    // peripherals
    //     .RCC
    //     .ctlr
    //     .modify(|r, w| unsafe { w.bits(r.bits() | 0x00000001) });
    // peripherals
    //     .RCC
    //     .cfgr0
    //     .modify(|r, w| unsafe { w.bits(r.bits() & 0x08FF0000) });
    // peripherals
    //     .RCC
    //     .ctlr
    //     .modify(|r, w| unsafe { w.bits(r.bits() & 0xFEF6FFFB) });
    // peripherals
    //     .RCC
    //     .ctlr
    //     .modify(|r, w| unsafe { w.bits(r.bits() & 0xFFFBFFFF) });
    // peripherals
    //     .RCC
    //     .cfgr0
    //     .modify(|r, w| unsafe { w.bits(r.bits() & 0xFF00FFFF) });
    // peripherals
    //     .RCC
    //     .intr
    //     .write(|w| unsafe { w.bits(0x009F0000) });
}

static mut P: *mut Peripherals = 0 as *mut Peripherals;
static mut DMA_BUF1: [u8; 1024] = [0u8; 1024];
static mut usart1: *mut MyUsart = 0 as *mut MyUsart;
static mut tasks: Queue<TaskStatus, 10> = Queue::new();

enum TaskStatus {
    Usart1_DMA_Receive_Complete,
}

#[ch32l1_macro::interrupt_handler(SysTick_Handler)]
fn SysTick_Handler_1() {}

#[ch32l1_macro::interrupt_handler(DMA1_Channel5_IRQHandler)]
fn DMA1_Channel5_IRQHandler_1() {
    // let usart1 = &*usart1;
    unsafe {
        // tasks.enqueue(TaskStatus::Usart1_DMA_Receive_Complete);
        (*P).DMA.intfcr.write(|w| w.ctcif5().set_bit());
    }
}
extern "C" {
    static _eusrstack: u8;
}
mod runtime;
#[no_mangle]
fn main() -> ! {
    let mut peripherals = unsafe { ch32l103::Peripherals::steal() };
    let mut dma_buf1 = [0u8; 1024];
    unsafe { P = &mut peripherals };

    make_cpu_fullspeed(&peripherals);

    // 使能 gpioa,spi1 时钟
    peripherals
        .RCC
        .apb2pcenr
        .modify(|_, w| w.iopaen().set_bit().spi1en().set_bit().iopben().set_bit());

    use drivers::gpio::GPIO;
    let mut gpio_a0: drivers::gpio::GPIO<'A', 0> = drivers::gpio::GPIO::get(&peripherals);
    gpio_a0.set_mode(CNF::AnalogInput, drivers::gpio::MODE::MHz50);
    let mut gpio_a1: drivers::gpio::GPIO<'A', 1> = drivers::gpio::GPIO::get(&peripherals);
    gpio_a1.set_mode(CNF::AnalogInput, drivers::gpio::MODE::MHz50);
    let mut gpio_a2: drivers::gpio::GPIO<'A', 2> = drivers::gpio::GPIO::get(&peripherals);
    gpio_a2.set_mode(CNF::AnalogInput, drivers::gpio::MODE::MHz50);

    let mut delay1 = MyDelay::new(&peripherals.SYSTICK, &peripherals);
    let mut delay2 = MyDelay::new(&peripherals.SYSTICK, &peripherals);
    let mut delay = MyDelay::new(&peripherals.SYSTICK, &peripherals);

    // PB0 是DC引脚 、RES是PA3
    // let dc = MyOutputPin_B0::new(&peripherals.GPIOB);
    let mut dc: GPIO<'B', 0> = GPIO::get(&peripherals);
    dc.set_mode(CNF::AnalogInput, drivers::gpio::MODE::MHz50);
    // let mut res = MyOutputPin_A3::new(&peripherals.GPIOA);
    let mut res: GPIO<'A', 3> = GPIO::get(&peripherals);
    res.set_mode(CNF::AnalogInput, drivers::gpio::MODE::MHz50);
    let spi1 = &peripherals.SPI1;
    let interface = SPIInterface::new(MySpi::new(spi1, &mut delay1, &peripherals), dc);
    let mut display: Ssd1306<
        SPIInterface<MySpi<'_>, GPIO<'B', 0>>,
        DisplaySize128x64,
        BufferedGraphicsMode<DisplaySize128x64>,
    > = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
        .into_buffered_graphics_mode();

    display.reset(&mut res, &mut delay2).unwrap();
    display.init().unwrap();
    display.clear(BinaryColor::Off).unwrap();

    let text_style = MonoTextStyleBuilder::new()
        .font(&FONT_7X14_BOLD)
        .text_color(BinaryColor::On)
        .build();

    let mut i = 0;
    let mut buffer = [0u8; 32];

    let text_style_width = text_style.font.character_size.width;
    let text_style_height = text_style.font.character_size.height;

    let current_freq = get_current_freq(&peripherals);

    let a = unsafe { &*P };
    let mut u = usart::MyUsart::new(&a.USART1, a, unsafe { &mut DMA_BUF1 });
    unsafe { usart1 = &mut u };
    // 配置中断
    peripherals
        .PFIC
        .ienr1
        .write(|w| unsafe { w.inten16_31().bits(0b10000000_00000000) });

    // let mut runtime = SimpleRuntime::new();
    // let mut task1 = &mut async {
    //     let u = unsafe { &*usart1 };
    //     u.dma_write().await;
    //     // (*usart1).dma_write(&mut dma_buf1, 1024);
    // } as &mut dyn Future<Output = ()>;
    // let task1_static: &'static mut dyn Future<Output = ()> = unsafe { transmute(task1) };
    // runtime.spawn(task1_static);
    // runtime.run();
    loop {
        unsafe {
            while let Some(task) = tasks.dequeue() {
                match task {
                    TaskStatus::Usart1_DMA_Receive_Complete => {
                        let s = get_stack_pointer();
                        let _ = (*usart1).write(&s.to_be_bytes());
                        let _ = (*usart1).write(&(&_eusrstack as *const u8 as u32).to_be_bytes());
                    }
                }
            }
        }

        let s = i.numtoa(10, &mut buffer);

        let text_rectangle = Rectangle::new(
            Point::zero(),
            Size::new(text_style_width * s.len() as u32, text_style_height),
        );
        display
            .fill_solid(&text_rectangle, BinaryColor::Off)
            .unwrap();

        match core::str::from_utf8(s) {
            Ok(ss) => {
                show_text(ss, &mut display, &text_style);
            }
            Err(err) => {
                show_text("error", &mut display, &text_style);
            }
        }
        display.flush().unwrap();
        i += 1;
        // let current_freq = get_current_freq(&peripherals);
        gpio_a0.set_high();
        gpio_a1.set_low();
        gpio_a2.set_low();
        // peripherals.PFIC.

        // usart1.write(b"abcde12345");
        delay.delay_ns(5_000_000);
        gpio_a0.set_low();
        gpio_a1.set_high();
        gpio_a2.set_low();

        // usart1.write(b"23333");
        delay.delay_ns(5_000_000);
        gpio_a0.set_low();
        gpio_a1.set_low();
        gpio_a2.set_high();

        // usart1.write(b"666");
        delay.delay_ns(5_000_000);
    }
}

async fn aaa() -> usize {
    1
}

fn get_stack_pointer() -> usize {
    let sp: usize;
    unsafe { asm!("mv {}, sp", out(reg) sp) };
    unsafe { &_eusrstack as *const u8 as usize - sp }
}

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

pub struct MySpi<'a> {
    raw_spi: &'a SPI1,
    delay: &'a mut MyDelay<'a>,
}

impl<'a> MySpi<'a> {
    fn new(raw_spi: &'a SPI1, delay: &'a mut MyDelay<'a>, peripherals: &Peripherals) -> Self {
        // 设置引脚复用，PA4、5、6、7
        peripherals.GPIOA.cfglr.modify(|_, w| {
            w.cnf4()
                .variant(0b10)
                .mode4()
                .variant(0b11)
                .cnf5()
                .variant(0b10)
                .mode5()
                .variant(0b11)
                .cnf6()
                .variant(0b01)
                .mode6()
                .variant(0b00)
                .cnf7()
                .variant(0b10)
                .mode7()
                .variant(0b11)
        });

        let mut a = 0;
        while raw_spi.statr.read().bsy().bit_is_set() {
            a += 1;
        }
        let c = a;
        raw_spi.ctlr1.modify(|_, w| w.spe().clear_bit());

        raw_spi.ctlr2.modify(|_, w| w.ssoe().set_bit());
        raw_spi.ctlr1.modify(|_, w| {
            w.cpol()
                .clear_bit() // 设置时钟 低电平空闲，第一个时钟沿采样
                .cpha()
                .clear_bit()
                .mstr()
                .set_bit() //设置主从
                .ssm()
                .clear_bit() //硬件控制NSS
                .ssi()
                .clear_bit()
                .br()
                .variant(0b010) //设置频率96/8=12
        });
        raw_spi.ctlr1.modify(|_, w| w.spe().set_bit());

        MySpi { raw_spi, delay }
    }
}

impl<'a> ErrorType for MySpi<'a> {
    type Error = embedded_hal::spi::ErrorKind;
}

impl<'a> SpiDevice for MySpi<'a> {
    fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> {
        operations.iter().for_each(|op| match op {
            Operation::Read(items) => {
                let a = 1;
            }
            Operation::Write(items) => {
                let mut temp: [u8; 0] = [];
                let _ = self.transaction(&mut [Operation::Transfer(&mut temp, *items)]);
            }
            Operation::Transfer(items, items1) => {
                items1.iter().for_each(|data| {
                    while self.raw_spi.statr.read().bsy().bit_is_set()
                        || self.raw_spi.statr.read().txe().bit_is_clear()
                    {}
                    self.raw_spi
                        .datar
                        .write(|w| unsafe { w.bits(*data as u16) });
                });
            }
            Operation::TransferInPlace(items) => {
                let mut temp: [u8; 0] = [];
                let _ = self.transaction(&mut [Operation::Transfer(&mut temp, *items)]);
            }
            Operation::DelayNs(ns) => {
                &self.delay.delay_ns(*ns);
            }
        });
        Ok(())
    }
}

pub struct MyDelay<'a> {
    systick: &'a SYSTICK,
    peripherals: &'a Peripherals,
}
impl<'a> MyDelay<'a> {
    fn new(systick: &'a SYSTICK, peripherals: &'a Peripherals) -> Self {
        MyDelay {
            systick,
            peripherals,
        }
    }
}
impl<'a> DelayNs for MyDelay<'a> {
    fn delay_ns(&mut self, ns: u32) {
        let current_freq = get_current_freq(self.peripherals);
        let instruction_per_us = current_freq / 1000_000;
        let instruction_count = {
            if ns >= 1000_000 {
                ns / 1000 * instruction_per_us
            } else if ns > 1000 {
                let instruction_count = ns / 1000 * instruction_per_us;
                let f = ns % 1000;
                let ns_per_instruction = 1000_000_000 / current_freq;
                instruction_count + (f / ns_per_instruction)
            } else {
                let ns_per_instruction = 1000_000_000 / current_freq;
                ns / ns_per_instruction
            }
        };
        debug_send(&0x87654321_u32.to_be_bytes());
        let start = self.systick.cntl().read().cntl().bits();
        debug_send(&start.to_be_bytes());
        self.systick.ctlr.modify(|_, w| {
            w.mode()
                .clear_bit()
                .stclk()
                .set_bit()
                .init()
                .set_bit()
                .ste()
                .set_bit()
        });
        while self.systick.cntl().read().cntl().bits() < instruction_count {}
        let middle = self.systick.cntl().read().cntl().bits();
        debug_send(&middle.to_be_bytes());
        self.systick.ctlr.modify(|_, w| {
            w.mode()
                .clear_bit()
                .stclk()
                .set_bit()
                .init()
                .set_bit()
                .ste()
                .clear_bit()
        });
        let last = self.systick.cntl().read().cntl().bits();
        debug_send(&last.to_be_bytes());
    }
}

enum FreqType {
    SYSCLK,
    HCLK,
    PCLK1,
    PCLK2,
}
pub fn get_current_freq(peripherals: &Peripherals) -> u32 {
    let internal_clock_freq: u32 = 8_000_000;
    let external_clock_freq: u32 = 8_000_000;
    // 确定SYSCLK的时钟
    let sysclk_freq = match peripherals.RCC.cfgr0.read().sws().bits() {
        0b00 => {
            // HSI
            internal_clock_freq
        }
        0b01 => {
            // HSE
            external_clock_freq
        }
        0b10 => {
            // PLL 获取PLL的倍数
            let pll_mul = peripherals.RCC.cfgr0.read().pllmul().bits();
            let pll_mul = match pll_mul {
                0b0111 => 18,
                _ => pll_mul + 2,
            };
            // 获取PLL的输入时钟，首先判断输入来源
            let pll_src_freq = if peripherals.RCC.cfgr0.read().pllsrc().bit_is_set() {
                // 来自HSE，判断HSE的分频数
                let hse_prescaler: u32 = if peripherals.RCC.cfgr0.read().pllxtpre().bit_is_set() {
                    2
                } else {
                    1
                };
                external_clock_freq / hse_prescaler
            } else {
                // 来自HSI，判断HSI的分频数
                let hsi_prescaler: u32 = if peripherals.EXTEN.exten_ctr.read().hsipre().bit_is_set()
                {
                    1
                } else {
                    2
                };
                internal_clock_freq / hsi_prescaler
            };
            pll_src_freq * pll_mul as u32
        }
        0b00 => {
            panic!("System clock source not available")
        }
        _ => {
            panic!("System clock source not available")
        }
    };
    // 获取HB的分频数
    let hpre = {
        let hpre = peripherals.RCC.cfgr0.read().hpre().bits();
        if hpre < 0b1000 {
            1
        } else {
            let temp = hpre & 0b0111;
            2u32.pow(temp as u32 + 1)
        }
    };
    sysclk_freq
}

pub fn make_cpu_fullspeed(peripherals: &Peripherals) {
    // 使能外部晶振
    peripherals.RCC.ctlr.modify(|_, w| w.hseon().set_bit());
    // 等待外部晶振稳定
    while peripherals.RCC.ctlr.read().hserdy().bit_is_clear() {}
    // 设置PLL源为HSE，HSE预分频器设置为不分频，PLL倍频为12
    peripherals.RCC.cfgr0.modify(|_, w| {
        w.pllsrc()
            .set_bit()
            .pllxtpre()
            .clear_bit()
            .pllmul()
            .variant(0b1010)
    });
    // 使能PLL
    peripherals.RCC.ctlr.modify(|_, w| w.pllon().set_bit());
    // 等待PLL就绪
    while peripherals.RCC.ctlr.read().pllrdy().bit_is_clear() {}
    // 设置FLASH的延迟访问周期（ACTLR寄存器）
    peripherals
        .FLASH
        .actlr
        .modify(|_, w| w.latency().variant(0b10));
    // 设置系统时钟输入为PLL
    peripherals.RCC.cfgr0.modify(|_, w| w.sw().variant(0b10));
    // 等待系统时钟状态为PLL
    while peripherals.RCC.cfgr0.read().sws().bits() != 0b10 {}

    // //使能内部晶振
    // peripherals.RCC.ctlr.modify(|_, w| w.hsion().set_bit());
    // //等待内部晶振稳定
    // while peripherals.RCC.ctlr.read().hsirdy().bit_is_clear() {}

    // //设置PLL的时钟来源为HSI
    // peripherals.RCC.cfgr0.modify(|_, w| w.pllsrc().clear_bit());
    // //设置HSI的预分频为1
    // peripherals
    //     .EXTEN
    //     .exten_ctr
    //     .modify(|_, w| w.hsipre().set_bit());
}

fn show_text<DI, SIZE>(
    str: &str,
    display: &mut Ssd1306<DI, SIZE, BufferedGraphicsMode<SIZE>>,
    text_style: &MonoTextStyle<'_, BinaryColor>,
) where
    DI: WriteOnlyDataCommand,
    SIZE: DisplaySize,
{
    // display.clear();
    Text::with_baseline(str, Point::zero(), *text_style, Baseline::Top)
        .draw(display)
        .unwrap();
}

fn debug_send(data: &[u8]) {
    // let p = unsafe { Peripherals::steal() };
    // let _ = usart::MyUsart::new(&p.USART1, &p).write(data);
}
